#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2021-present, sun-shine cloud, Inc.
# All rights reserved
# Author：  xiaobo
# Date：    2021-04-13
# 音频降噪任务处理的主程序，通过task.lst的文件来同步音频处理的任务
# 该程序可以支持多进程，暂时先使用抢占式方式；

import multiprocessing
import time
import datetime
import os
import publicfun
import subprocess
import json
import cfg
import taskClass
import logging_config

logger = logging_config.Config().get_config()
SLEEP_TIME=5
WAIT_TIME=0.08
#pid是启动时指定的进程号，如果其小于以前设定的值，可能会造成一些数据的丢失，最好是一个比较固定的值
def ts_worker(server, pid):

    server_fg = server+"_"+str(pid)
    task = taskClass.task()
    while True:
        try:        
            #先把自已锁定的任务解锁
            task.unlockTask(server_fg)
            #再锁定一条记录
            task.lockTask(server_fg)
            ret = task.getLockTask(server_fg)
            if not ret:
                raise Exception("暂无记录")
            result, info = task.shExecutor(ret)
            #result 是bool类型的内容 true：则执行调用成功,执行成功后，会放入到回调表中进行回调处理；
            taskid = str(ret["taskid"])
            ossUrl = str(ret["ossUrl"])
            if result:
                logger.info("任务处理成功: taskid: " + taskid + ", 对应音频地址 ossUrl:" + ossUrl)
                task.addCallbackTask(taskid, 0)
                task.delTask(taskid)
            else:
                logger.info("任务处理失败: taskid: " + taskid + ", 对应音频地址 ossUrl:" + ossUrl)
                task.updateTaskInfo(taskid, info)                
        except (Exception) as e:
            task.unlockTask(server_fg)
            if '暂无记录' != str(e):
                print(e)
            time.sleep(SLEEP_TIME)
        finally:
            time.sleep(WAIT_TIME)

#回调的运行程序
def cb_worker(server, pid):

    server_fg = server+"_cb_"+str(pid)
    task = taskClass.task()
    while True:
        try:        
            #先把自已锁定的任务解锁
            task.unlockCbTask(server_fg)
            #再锁定一条记录
            task.lockCbTask(server_fg)
            ret = task.getCbLockTask(server_fg)
            if not ret:
                raise Exception("暂无记录")
            taskid = str(ret["taskid"])
            logger.info("任务回调开始 taskid: " + taskid)
            result = task.callback(ret)
            #result 是bool类型的内容 true：则执行调用成功,执行成功后，会放入到回调表中进行回调处理；
            if result:
                logger.info("任务回调完成 taskid: " + taskid)
                task.addHistoryTask(taskid)
                task.delCbTask(taskid)
        except (Exception) as e:
            task.unlockCbTask(server_fg)
            time.sleep(SLEEP_TIME)
        finally:
            time.sleep(WAIT_TIME)

#定时清理多次未成功的任务
def clear_Task(server, pid):

    server_fg = server+"_cl_"+str(pid)
    task = taskClass.task()
    while True:
        try:        
            #锁定一条失败记录
            task.lockFaultTask(server_fg)
            #移走一条记录
            task.mvFaultTask(server_fg)
            #锁定一条回调失败记录
            task.lockFaultCbTask(server_fg)
            #移走一条记录
            task.mvFaultCbTask(server_fg)
        except (Exception) as e:
            logger.error(e)
            time.sleep(SLEEP_TIME)
        finally:
            time.sleep(WAIT_TIME)

if __name__ == '__main__':
    #该程序可以多线程进行处理，但处理的过程中需要锁定任务，否则会出现处理的问题
    server = cfg.hostname
    #该值为处理音频转码的进程数，因为其处理时间相对较长，可能需要的进程数相对大一些；
    process1 = cfg.process1
    #该值为处理用户提交的进程数
    process2 = cfg.process2
    #该值是处理失败回收的进程
    process3 = cfg.process3

    for pid in range(0, process1):
        p = multiprocessing.Process(target = ts_worker, args=(server, pid, ))
        p.start()
    for pid in range(0, process2):
        p1 = multiprocessing.Process(target = cb_worker, args=(server, pid, ))
        p1.start()
    for pid in range(0, process3):
        p2 = multiprocessing.Process(target = clear_Task, args=(server, pid, ))
        p2.start()        
    p2.join()  # 主进程等待子进程结束，主进程再接着执行
    print("主进程执行结束，子进程是依附于主进程存在的，所以，子进程都结束后，主进程才真正的结束。")